﻿/**
   В данном классе описывается окружающая среда.
   данный компонент будет опрашиваться графическими элементами, и будет сообщать, можно ли двигаться объекту в данном направлении. Видно ли падающую звезду в округе. Или вообще видно ли звезд

 */

(function () {
    "use strict";

    F.Environment = function (container) {
        var self = this;
        self.container = container;
        //Здесь можно задать игровое пространство, и задавать произвольный масштаб картинки, и 
        //Вычислять x,y,width, height в зависимости от этого

        self.stars = [];
        self.aqualungers = [];
        self.compressor = null;

        //Координаты, внутри которых может происходить игровое действие
        self.realCoord = {
            x: 20,
            y: 200,
            width: 720,
            height: 465
        };

        self.startPositionAqualunger = { x: 600, y: 540};

        //Область видимости
        /**
         *	Аквалангист видит треть вокруг себя.
         *  Радиус - делим диаметр на 2
         */
        self.radiusVisibility = self.getGameBox().width / (3 * 2); 

        //Области для плавания и подъема
        var borderRightLeft = 30;
        self.borderOfBottom = { 
            x: borderRightLeft, 
            y: 65, 
            width: self.realCoord.width - borderRightLeft * 2, 
            height: 20 
        };
        self.areaForLifting = {
            x: 595,
            y: self.borderOfBottom.y,
            width: 20,
            height: 550 - self.borderOfBottom.y
        };
        self.areaBoat = {
            x: 545,
            y: 535,
            width: 80,
            height: 10
        }
    };

    var ep = F.Environment.prototype;
    
    ep.getStartPositionAqualunger = function(){
        var self = this;
        return self.startPositionAqualunger;
    }

    ep.removeAqualunger = function(){
        var self = this;
        for (var i = 0; i < self.aqualungers.length; i++){
            if (!self.aqualungers[i].isGoOut()){
                self.aqualungers[i].goOut();   
                break;
            }
        }
    }
    

    /**
    Транислирование игровых координат в настояие
    */
    ep.translateGameToReal = function (x, y) {
        var self = this;
        var realX = x + self.realCoord.x;
        var realY = self.realCoord.y + self.realCoord.height - y;
        return { x: realX, y: realY };
    };

    /**
       Транслирование настоящих координат в игровые
     */
    ep.translateRealToGame = function (x, y) {
        var self = this;
        var gameX = x - self.realCoord.x
        var gameY = self.realCoord.y + self.realCoord.height - y;
        return { x: gameX, y: gameY };
    };

    /**
       Возвращает границы игровых координат
     */
    ep.getGameBox = function () {
        var self = this;
        return { x: 0, y: 0, width: self.realCoord.width, height: self.realCoord.height };
    };

    /**
       Возвращает дно на котором может плавать аквалангист
     */
    ep.getBorderOfBottom = function(){
        var self = this;
        return self.borderOfBottom;
    }

    ep.getAreaForLifting = function () {
        var self = this;
        return self.areaForLifting;
    }

    ep.getAreaBoat = function(){
        var self = this;
        return self.areaBoat;
    }

    ep.getCompressor = function(aqualunger){
        //Проверяем, находится ли аквалангист на лодке.
        var self = this;
        var insideBoat = self.isDriverOnBase(aqualunger);
        if (!insideBoat)
            throw "Logical error. The diver can not access to the compressor, if it is not on the boat.";
        return self.compressor;
    }

    ep.isDriverOnBase = function(aqualunger){
        var self = this;
        var aquaX = aqualunger.getX(),
            aquaY = aqualunger.getY();
        var boatArea = self.getAreaBoat();
        return  boatArea.x <= aquaX &&
                boatArea.x + boatArea.width >= aquaX &&
                boatArea.y <= aquaY &&
                boatArea.y + boatArea.height >= aquaY;
    }

    ep.isPassedThirdScreen = function (aqualunger) {
        var self = this;
        var aquaY = aqualunger.getY();

        var areaForLifting = self.getAreaForLifting();
        return (areaForLifting.height / 3) < aquaY;
    }

    ep.isPassedSecondThirdScreen = function (aqualunger) {
        var self = this;
        var aquaY = aqualunger.getY();

        var areaForLifting = self.getAreaForLifting();
        return (2 * areaForLifting.height / 3) < aquaY;
    }

    ep.isPassedFourFifthsScreen = function (aqualunger) {
        var self = this;
        var aquaY = aqualunger.getY();

        var areaForLifting = self.getAreaForLifting();
        return (4 * areaForLifting.height / 5) < aquaY;
    }

    ep.isDriverOnBottom = function(aqualunger){
        var self = this;
        var bottomArea = self.getBorderOfBottom();
        return bottomArea.y <= aqualunger.getY() && bottomArea.y + bottomArea.height >= aqualunger.getY();   
    }

    ep.isDriverOnLiftingArea = function (aqualunger) {
        var self = this;
        var verticalArea = self.getAreaForLifting();
        return verticalArea.x <= aqualunger.getX() && verticalArea.x + verticalArea.width >= aqualunger.getX();
    }

    ep.validateRealCoordForStar = function(x,y){
        var self = this;
        var airPixels = 130; //Возможность кидать звезды с поверхности
        return  self.realCoord.x < x &&
                self.realCoord.y - airPixels < y &&
                self.realCoord.x + self.realCoord.width > x &&
                self.realCoord.y + self.realCoord.height > y;
    }

    ep.getVisibleStars = function(aqualunger){
        var self = this;
        var visibleStars = [];
        for (var i = 0, length = self.stars.length; i < length; i++) {
            if (self.isVisibleStar(aqualunger, self.stars[i])) {
                visibleStars.push(self.stars[i]);    
            }
        }    
        return visibleStars;
    }

    /**
       Проверка, что звезда находится в радиусе видимости аквалангиста
       Проверка осуществляется в два этапа. 
       1) Определяется, что звезда за пределами квадрата видимости
       2) Что звезда внутри квадрата, и определяется более точно, видна ли звезда
     */
    ep.isVisibleStar= function (aqualunger, star) {
        var self = this;
        var starX = star.getX();
        var starY = star.getY();
        var aquaX = aqualunger.getX();
        var aquaY = aqualunger.getY();
        var radVis = self.radiusVisibility;
        
        //Звезда находится внутри бокса видимости
        var isInsideBox =   starX > aquaX - radVis && 
                            starX < aquaX + radVis &&
                            starY > aquaY - radVis &&
                            starY < aquaY + radVis;
        if (isInsideBox) {
            //Проверяем более точно
            return Math.pow(starX - aquaX, 2) + Math.pow(starY - aquaY, 2) < Math.pow(radVis, 2);
        }
        
        return false;
    }

    ep.registerStar = function(star){
        if (!star)
            throw "Logical error. Transferred to the null object.";
        var self = this;
        self.stars.push(star);
    }

    ep.unregisterStar = function (star) {
        if (!star)
            throw "Logical error. Transferred to the null object.";
        var self = this;
        for (var i = 0, length = self.stars.length; i < length; i++) {
            if (self.stars[i] === star) {
                self.stars.splice(i, 1);
                break;
            }
        }
    }

    ep.registerAqualunger = function(aqualunger){
        if (!aqualunger)
            throw "Logical error. Transferred to the null object.";
        var self = this;
        self.aqualungers.push(aqualunger);
    }

    ep.unregisterAqualunger = function (aqualunger) {
        if (!aqualunger)
            throw "Logical error. Transferred to the null object.";
        var self = this;
        for (var i = 0, length = self.aqualungers.length; i < length; i++) {
            if (self.aqualungers[i] === aqualunger) {
                self.aqualungers.splice(i, 1);
                break;
            }
        }
    }

    ep.setCompressor = function(compressor){
        var self = this;
        self.compressor = compressor;
    }

    ep = null;
} ());